#ifndef PERLINNOISE_H_
#define PERLINNOISE_H_

struct Gradient1d {
	float x;
};

struct Gradient2d {
	float x;
	float y;
};

struct Gradient3d {
	float x;
	float z;
	float t;
};

class PerlinNoise
{
public:
	PerlinNoise();
	virtual ~PerlinNoise();
	
	Gradient1d Gradient(int x, int frequency);
	int PerlinNoise1d(int x);
	float PerlinNoise1d(float x, int frequency);
	
	int PerlinNoise2d(int x, int z, int width, int height);
	float PerlinNoise2d(float x, float z, int frequency);
	
	int PerlinNoise3d(int x, int z, float t, int width, int height);	
	float PerlinNoise3d(float x, float z, float t, int frequency);
			
	Gradient2d Gradient(int x, int z, int frequency); /* gradient of a point (x, z) is a vector in 2D space */
	Gradient3d Gradient(int x, int z, int t, int frequency); /* gradient of a point (x, z, t) is a vector in 3D space */
	
private:
	/* gradient vector */	
	Gradient1d* gradient1d;
	Gradient2d* gradient2d;
	Gradient3d* gradient3d;
	int gradientSize;
	int* permutation;
	
	int rankCount;	
	int* frequency; /* the number of nodes corresponding to each rank */
	
	float* amplitude;
	float* persistence;
	/* frequency = 2^i; amplitude = persistence^i; i in [0, rankCount-1] */
	
	/* init and cleanup */
	void InitPerlinNoise();
	void CleanupPerlinNoise();	
public:	
	int GetRankCount();
};

#endif /*PERLINNOISE_H_*/
